/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.document.service;

import com.alibaba.fastjson2.JSONObject;
import com.google.common.collect.Lists;
import com.je.common.base.document.FileBound;
import com.je.document.model.FileBO;
import com.je.document.model.FileUpload;
import com.je.ibatis.extension.plugins.pagination.Page;
import java.io.InputStream;
import java.util.List;

/**
 * 文档操作基础Service
 *
 * @author wangmm@ketr.com.cn
 * @date 2019/8/27
 */
public interface DocumentService {

    //------------------------------------文件上传保存

    /**
     * 保存上传附件(单个)
     *
     * @param fileUploadFile 上传请求附件
     * @param userId         用户ID
     * @return java.util.List<com.je.paas.document.model.bo.FileBO>
     */
    default FileBO saveSingleFile(FileUpload fileUploadFile, String userId) {
        return saveSingleFile(fileUploadFile, userId, null, null);
    }

    /**
     * 保存上传附件(单个)
     *
     * @param fileUploadFile 上传请求附件
     * @param userId         用户ID
     * @param metadata       文件业务元数据,JSONObject格式,key范围为 MetadataEnum
     * @return java.util.List<com.je.paas.document.model.bo.FileBO>
     */
    default FileBO saveSingleFile(FileUpload fileUploadFile, String userId, JSONObject metadata) {
        return saveSingleFile(fileUploadFile, userId, metadata, null);
    }

    /**
     * 保存上传附件(单个)
     *
     * @param fileUploadFile 上传请求附件
     * @param userId         用户ID
     * @param bucket         存储空间标识
     * @return java.util.List<com.je.paas.document.model.bo.FileBO>
     */
    default FileBO saveSingleFile(FileUpload fileUploadFile, String userId, String bucket) {
        return saveSingleFile(fileUploadFile, userId, null, bucket);
    }

    /**
     * 保存上传附件(单个)
     *
     * @param fileUploadFile 上传请求附件
     * @param userId         用户ID
     * @param metadata       文件业务元数据,JSONObject格式,key范围为 MetadataEnum
     * @param bucket         存储空间标识
     * @return java.util.List<com.je.paas.document.model.bo.FileBO>
     */
    default FileBO saveSingleFile(FileUpload fileUploadFile, String userId, JSONObject metadata, String bucket) {
        List<FileBO> fileBOS = saveFile(Lists.newArrayList(fileUploadFile), userId, metadata, bucket, null);
        if (fileBOS == null || fileBOS.isEmpty()) {
            return null;
        }
        return fileBOS.get(0);
    }

    /**
     * 绑定文件为附件（单个）
     *
     * @param fileBoundFile 需要绑定得文件
     * @param userId        用户ID
     * @param metadata      文件业务元数据，JSONObject格式，key范围为MetadataEnum
     * @param bucket        存储空间标识
     * @return 附件信息
     */
    default FileBO boundSingleFile(FileBound fileBoundFile, String userId, JSONObject metadata, String bucket) {
        List<FileBO> fileBOS = boundFile(Lists.newArrayList(fileBoundFile), userId, metadata, bucket);
        if (fileBOS == null || fileBOS.isEmpty()) {
            return null;
        }
        return fileBOS.get(0);
    }

    /**
     * 保存上传附件(多个)
     *
     * @param fileUploadFiles 上传请求附件
     * @param userId          用户ID
     * @return java.util.List<com.je.paas.document.model.bo.FileBO>
     */
    default List<FileBO> saveFile(List<FileUpload> fileUploadFiles, String userId) {
        return saveFile(fileUploadFiles, userId, null, null, null);
    }

    /**
     * 保存上传附件(多个)
     *
     * @param fileUploadFiles 上传请求附件
     * @param userId          用户ID
     * @param metadata        文件业务元数据,JSONObject格式,key范围为 MetadataEnum
     * @return java.util.List<com.je.paas.document.model.bo.FileBO>
     */
    default List<FileBO> saveFile(List<FileUpload> fileUploadFiles, String userId, JSONObject metadata) {
        return saveFile(fileUploadFiles, userId, metadata, null, null);
    }

    /**
     * 保存上传附件(多个)
     *
     * @param fileUploadFiles 上传请求附件
     * @param userId          用户ID
     * @param bucket          存储空间标识
     * @return java.util.List<com.je.paas.document.model.bo.FileBO>
     */
    default List<FileBO> saveFile(List<FileUpload> fileUploadFiles, String userId, String bucket) {
        return saveFile(fileUploadFiles, userId, null, bucket, null);
    }

    /**
     * 保存上传附件(多个)
     *
     * @param fileUploadFiles 上传请求附件
     * @param userId          用户ID
     * @param metadata        文件业务元数据,JSONObject格式,key范围为 MetadataEnum
     * @param bucket          存储空间标识
     * @return java.util.List<com.je.paas.document.model.bo.FileBO>
     */
    default List<FileBO> saveFile(List<FileUpload> fileUploadFiles, String userId, JSONObject metadata, String bucket) {
        return saveFile(fileUploadFiles, userId, metadata, bucket, null);
    }

    /**
     * 保存上传附件(多个)
     *
     * @param fileUploadFiles 上传请求附件
     * @param userId          用户ID
     * @param metadata        文件业务元数据,JSONObject格式,key范围为 MetadataEnum
     * @param bucket          存储空间标识
     * @param dir             文件存储目录
     * @return java.util.List<com.je.paas.document.model.bo.FileBO>
     */
    List<FileBO> saveFile(List<FileUpload> fileUploadFiles, String userId, JSONObject metadata, String bucket, String dir);

    /**
     * 绑定附件（多个）
     *
     * @param fileBounds 需要绑定文件
     * @param userId     用户ID
     * @param metadata   元数据
     * @param bucket     存储桶标识
     * @return
     */
    List<FileBO> boundFile(List<FileBound> fileBounds, String userId, JSONObject metadata, String bucket);

    //------------------------------------文件元数据操作

    /**
     * 保存附件业务元数据
     *
     * @param userId   用户ID
     * @param metadata 文件业务元数据,JSONObject格式,key范围为 MetadataEnum
     * @param fileKeys 文件标识,可包含多个使用','分隔
     */
    void saveFileMetadata(String userId, JSONObject metadata, List<String> fileKeys);

    /**
     * 保存附件业务元数据
     *
     * @param userId   用户ID
     * @param metadata 文件业务元数据,JSONObject格式,key范围为 MetadataEnum
     * @param relId    业务关联ID
     * @param fileId   文件ID
     */
    void saveFileMetadata(String userId, JSONObject metadata, String relId, String fileId);

    /**
     * 更新业务元数据
     *
     * @param fileKey    文件唯一key
     * @param newRelName 文件新名称
     * @param metadata   元数据
     * @param userId     操作用户ID
     */
    void updateMetadataByKey(String fileKey, String newRelName, JSONObject metadata, String userId);

    /**
     * 获取文件元数据
     *
     * @param fileKey 文件唯一key
     * @return com.alibaba.fastjson.JSONObject
     */
    JSONObject selectFileMetadataByKey(String fileKey);

    /**
     * 修改文件
     *
     * @param fileKey     文件唯一key
     * @param inputStream 新文件输入流
     * @param userId      操作用户ID
     * @return com.je.paas.document.model.bo.FileBO
     */
    FileBO editByFileKey(String fileKey, InputStream inputStream, String userId);

    //------------------------------------文件复制删除

    /**
     * 复制文件引用及其业务元数据
     *
     * @param fileKey    文件唯一key
     * @param newRelName 文件新名称
     * @param metadata   元数据(会对被复制文件的元数据进行覆盖)
     * @param userId     操作用户ID
     * @return void
     */
    FileBO copyRelByKey(String fileKey, String newRelName, JSONObject metadata, String userId);

    /**
     * 逻辑删除指定文件
     *
     * @param fileKeys 文件唯一key集合
     * @param userId   操作人ID
     */
    void delFilesByKey(List<String> fileKeys, String userId);

    /**
     * 物理删除指定文件
     *
     * @param fileKeys 文件唯一key集合
     * @param userId   操作人ID
     */
    void deleteByFileKeys(List<String> fileKeys, String userId);

    //------------------------------------文件查找(唯一key查找，元数据条件查找)

    /**
     * 校验文件是否存在
     *
     * @param fileKey 文件唯一key
     * @return boolean
     */
    boolean exists(String fileKey);

    /**
     * 获取文件信息,不包含文件流
     *
     * @param fileKey 文件唯一key
     * @return com.je.paas.document.model.bo.FileBO
     */
    FileBO selectFileByKey(String fileKey);

    /**
     * 获取历史版本文件信息,不包含文件流
     *
     * @param fileKey 文件唯一key
     * @param version 版本号
     * @return com.je.paas.document.model.bo.FileBO
     */
    FileBO selectFileByKeyAndVersion(String fileKey, String version);

    /**
     * 获取文件信息集合,不包含文件流
     *
     * @param keys 文件唯一key集合
     * @return java.util.List<com.je.paas.document.model.bo.FileBO>
     */
    List<FileBO> selectFileListByKey(List<String> keys);

    /**
     * 根据元数据信息查找文件业务关联表数据
     *
     * @param metadataQuery 文件业务元数据,JSONObject格式,key范围为 MetadataEnum
     * @return void
     */
    List<FileBO> selectFileByMetadata(JSONObject metadataQuery);

    /**
     * selectFileByMetadata 方法返回值的基础上加入附件的文件流
     *
     * @param metadataQuery 文件业务元数据,JSONObject格式,key范围为 MetadataEnum
     * @return void
     * @see #selectFileByMetadata
     */
    List<FileBO> selectFileFullByMetadata(JSONObject metadataQuery);

    /**
     * 根据元数据信息查找文件业务关联表数据-分页
     *
     * @param metadataQuery 文件业务元数据,JSONObject格式,key范围为 MetadataEnum
     * @param start         开始行
     * @param limit         每页行数
     * @param orderBy       排序
     * @return void
     */
    Page<FileBO> selectFilePageByMetadata(JSONObject metadataQuery, int start, int limit, String orderBy);

    //------------------------------------文件流读取

    /**
     * 读取文件,包含文件流(无日志)
     *
     * @param fileKey 文件唯一key
     * @return com.je.paas.document.model.bo.FileBO
     */
    FileBO readFile(String fileKey);

    /**
     * 读取历史文件,包含文件流(无日志)
     *
     * @param fileKey 文件唯一key
     * @return com.je.paas.document.model.bo.FileBO
     */
    FileBO readFile(String fileKey, String version);

    /**
     * 预览文件,包含文件流(会记录日志)
     *
     * @param fileKey 文件唯一key
     * @param userId  用户ID
     * @return java.io.InputStream
     */
    FileBO previewFile(String fileKey, String userId);

    /**
     * 预览文件,包含文件流(会记录日志)
     *
     * @param fileKey 文件唯一key
     * @param userId  用户ID
     * @param version 版本号
     * @return java.io.InputStream
     */
    FileBO previewFile(String fileKey, String userId, String version);

    /**
     * 下载文件,包含文件流(会记录日志)
     *
     * @param fileKey 文件唯一key
     * @param userId  用户ID
     * @return java.io.InputStream
     */
    FileBO downloadFile(String fileKey, String userId);

    /**
     * 下载文件,包含文件流(会记录日志)
     *
     * @param fileKey 文件唯一key
     * @param userId  用户ID
     * @param version 版本信息
     * @return java.io.InputStream
     */
    FileBO downloadFile(String fileKey, String userId, String version);

    /**
     * 获取缩略图
     *
     * @param fileKey 文件唯一key
     * @return java.io.InputStream
     */
    InputStream thumbnail(String fileKey);

    /**
     * 打包zip
     *
     * @param fileKeys 文件唯一key集合
     * @return java.io.InputStream
     */
    InputStream buildZip(List<String> fileKeys);

    /**
     * 根据fileKey获取所有版本的文件
     * @param fikeKey 文件唯一key
     * @return
     */
    List<FileBO> selectAllVersionFiles(String fikeKey);

    /**
     * 根据fileKey获取所有版本的文件
     * @param fikeKey 文件唯一key
     * @return
     */
    FileBO selectVersionFile(String fikeKey, int version);
}